// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

#ifndef CANGJIE_MIGRATOR_IMPORT_INFO
#define CANGJIE_MIGRATOR_IMPORT_INFO

#include "cangjie/AST/Node.h"

#include <string>
#include <vector>

#include "Rules/ImportRule.h"
#include "PackageExpression.h"
#include "PositionRange.h"

namespace CangjieMigrator {

class ImportInfo {
public:
    static std::unique_ptr<ImportInfo> Build(const Cangjie::AST::ImportSpec &node, const PositionRange &range);

    ImportInfo(std::string package, std::string modifier, const PositionRange &positionRange);
    virtual ~ImportInfo() = default;

    // return true: Need to remove
    virtual bool TryModifyOrRemove(const Rules::ImportRule &rule);

    // return true: Triggered a replacement action
    bool TryReplacePackage(const std::string &source, const std::string &target);

    enum class Type {
        IMPORT_IDENTIFIER,
        IMPORT_ALIAS,
        IMPORT_ALL,
    };
    [[nodiscard]] virtual Type GetType() const = 0;
    [[nodiscard]] virtual bool IsImplicit() const;

    virtual void ExportTo(std::vector<PackageExpression> &v) const = 0;

    [[nodiscard]] virtual std::string ToString() const = 0;

    const PositionRange positionRange;

protected:
    [[nodiscard]] std::string GenerateModifier() const;

    std::string package;
    std::string modifier;
};

class ImportIdentifierInfo final : public ImportInfo {
public:
    static std::unique_ptr<ImportInfo> BuildSingle(const Cangjie::AST::ImportSpec &import, const PositionRange &range);
    static std::unique_ptr<ImportInfo> BuildMulti(const Cangjie::AST::ImportSpec &import, const PositionRange &range);

    ImportIdentifierInfo(std::string package, std::vector<std::string> identifiers, std::string modifier = "",
        const PositionRange &positionRange = PositionRange::Empty());
    ImportIdentifierInfo(std::string package, std::string identifier, std::string modifier = "",
        const PositionRange &positionRange = PositionRange::Empty());
    explicit ImportIdentifierInfo(const PackageExpression &expression);

    bool TryModifyOrRemove(const Rules::ImportRule &rule) override;

    [[nodiscard]] Type GetType() const override;

    void ExportTo(std::vector<PackageExpression> &v) const override;

    [[nodiscard]] std::string ToString() const override;

private:
    std::vector<std::string> identifiers;
};

class ImportAliasInfo final : public ImportInfo {
public:
    static std::unique_ptr<ImportInfo> Build(const Cangjie::AST::ImportSpec &import, const PositionRange &range);

    ImportAliasInfo(std::string package, std::string identifier, std::string modifier, std::string alias,
        const PositionRange &positionRange);

    bool TryModifyOrRemove(const Rules::ImportRule &rule) override;

    [[nodiscard]] Type GetType() const override;

    void ExportTo(std::vector<PackageExpression> &v) const override;

    [[nodiscard]] std::string ToString() const override;

private:
    std::string identifier;
    std::string alias;
};

class ImportAllInfo final : public ImportInfo {
public:
    static std::unique_ptr<ImportInfo> Build(const Cangjie::AST::ImportSpec &import, const PositionRange &range);

    ImportAllInfo(std::string package, std::string modifier, const PositionRange &positionRange);

    [[nodiscard]] Type GetType() const override;
    [[nodiscard]] bool IsImplicit() const override;

    void ExportTo(std::vector<PackageExpression> &v) const override;

    [[nodiscard]] std::string ToString() const override;
};

} // namespace CangjieMigrator

#endif // CANGJIE_MIGRATOR_IMPORT_INFO
